iT邦幫忙

DAY 20
4

資訊學院的30門課系列 第 20

資訊學院的30門課-演算法與google code jam

  • 分享至 

  • xImage
  •  

Google Code Jam 2009我參加過一次,依當時的評分標準,至少要能寫出一題,能夠在限定時間內跑完的code,才能晉級。但是幾乎都是要用dynamic programming的技巧,我用遞迴解一題後,想當然爾,效能不佳,所以我就放棄了。

大家可以上去看看
http://code.google.com/codejam/
談到google程式大賽

雖然我不曉得程式怎麼寫效能才高,但可以分享為甚麼我的程式跑的慢,為甚麼大的資料集運算很慢,一般網頁或視窗是程式設計課程中,都沒有注重在如何讓程式跑的最快,有志參加的coder,一定要記得這些重點才能晉級。

2011我做的是第三題

Problem C. Candy Splitting
http://code.google.com/codejam/contest/dashboard?c=975485#s=p2

提示一下,弟弟的加法就是XOR,哥哥才會進位的加法。這樣題目就容易理解了。

像我這種程式效能上的差異,不是單純使用高級硬體就能cover掉的。

#include <cstdlib>
#include <iostream>
#include <stdio.h>
 
using namespace std;
 
int main(int argc, char *argv[])
{
    int compute(int *candy, int candyNum, int s, int x, int p, int max);
    
    FILE *input;
    int i, j, x, sum, ans;
    int looptime, candyNum;
    int candy[1001];
    input = fopen("D:\\Dev-Cpp\\3-test.txt","ro");
    fscanf(input,"%d",&looptime);
    for(i=0; i<looptime; i++) {
        fscanf(input,"%d",&candyNum); 
        sum = 0;
        x = 0;
        for(j=0; j<candyNum; j++) {
            fscanf(input,"%d",&candy[j]);             
//            sum += candy[j];
        }
        for(j=0; j<candyNum; j++) {
            //printf("%d ", candy[j]);        
            sum += candy[j];
            x ^= candy[j];
        }      
        //printf("=%d",sum);
 
        ans = compute(candy, candyNum, sum, x, 0, 0);        
        printf("Case #%d: ", i+1); 
        if(ans==0) {
            printf("NO\n");         
        }else{
            printf("%d\n", ans);         
        }
        fflush(stdout);
         
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}
 
int compute(int *candy, int candyNum, int s, int x, int p, int max) {
    int max1,max2;
    int a, b;
    
    if( candyNum == 0 ) {
        return max;
    }
    
    a = x ^ candy[0];
    b = p ^ candy[0];
    
 
    if(a == b) {
        max = (max<(s - candy[0]))? (s - candy[0]): max;            
    }
    //printf("[ a=%d, b=%d, x=%d, p=%d, max=%d ]", a, b, x, p, max);
 
    max1 = compute(candy+1, candyNum-1, s-candy[0], a, b, max);
    max2 = compute(candy+1, candyNum-1, s,          x, p, max);
    
    return (max1>max2)?max1:max2;      
}

這邊用到recursive去解,雖然CS教科書上recursive的例子很多,但在google code jam的題目中,幾乎都是效能殺手。
max1 = compute(candy+1, candyNum-1, s-candy[0], a, b, max);
max2 = compute(candy+1, candyNum-1, s, x, p, max);
因為例如「第三堆到第六堆的XOR」與「第四堆到第七堆的XOR」,其中「第四堆到第六堆的XOR」是不是被重複算了。
資料集越大,被重複算的運算就越多,程式就越慢。
到這邊是不是有大大已經想到,大的資料集要怎麼處理了呢?

更多鐵人賽分享內容:http://ithelp.ithome.com.tw/event/ironman4/index/personal/page/3/user/20030355


上一篇
資訊學院的30門課-計算機組織與結構(續)
下一篇
資訊學院的30門課-演算法(續)
系列文
資訊學院的30門課30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
modernsarah
iT邦研究生 4 級 ‧ 2011-10-18 08:52:54

Google學問多~
拍手

0
krarm
iT邦好手 1 級 ‧ 2011-10-18 14:36:10

我view一下google上別人寫的code,
http://code.google.com/codejam/contest/scoreboard?c=975485#vf=1
好像不用dynamic programming,是我想太多或想不夠多...
我再思考反省一下...

我要留言

立即登入留言